package cc.magicjson;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.Collections;

@SpringBootApplication(exclude = JmxAutoConfiguration.class)
public class GracefulShutdownApplication {

	@Value("${server.default-port}")
	private int defaultPort;

	@Value("${server.available-ports}")
	private int[] availablePorts;

	public static void main(String[] args) {

		SpringApplication application = new SpringApplication(GracefulShutdownApplication.class);
		application.setDefaultProperties(Collections.singletonMap("spring.jmx.enabled", "false"));
		application.run(args);
	}

	@Bean
	public WebServerFactoryCustomizer<TomcatServletWebServerFactory> webServerFactoryCustomizer() {
		return factory -> {
			int port = getAvailablePort(defaultPort, availablePorts);
			System.setProperty("server.port", String.valueOf(port));
			factory.setPort(port);
		};
	}

	private int getAvailablePort(int defaultPort, int[] availablePorts) {
		if (!isPortInUse(defaultPort)) {
			return defaultPort;
		}

		for (int port : availablePorts) {
			if (!isPortInUse(port)) {
				return port;
			}
		}

		throw new IllegalStateException("No available ports in the specified range.");
	}

	private boolean isPortInUse(int port) {
		try (ServerSocket socket = new ServerSocket(port)) {
			return false;
		} catch (IOException e) {
			return true;
		}
	}
}

